import { EventSourcePolyfill, type EventSourcePolyfillInit } from 'event-source-polyfill';
import { authStore } from "@/store";
import axios from 'axios';

const baseURL = import.meta.env.VITE_BASE_URI;

/**
 * SSE 客户端 (基于 event-source-polyfill)
 * 支持自定义请求头、自动重连、心跳检测等功能
 */
class SSE<T = any> {
    private url: string;// SSE 服务端 URL
    private options: SSEOptions<T>;// 配置选项
    private eventSource: EventSourcePolyfill | null = null;// SSE 客户端实例
    private reconnectTimer: number | null = null;// 重连定时器
    private heartbeatTimer: number | null = null;// 心跳定时器
    private lastMessageTime: number = 0;// 上次收到消息时间
    private isConnected: boolean = false;// 是否已连接
    private isDisconnecting: boolean = false;// 是否正在断开连接
    private reconnectAttempts: number = 0;// 重连次数
    private maxReconnectAttempts: number = 5;// 最大重连次数
    private isRefreshingToken: boolean = false; // 添加 token 刷新状态标记

    /**
     * 构造函数
     * @param url SSE 服务端 URL
     * @param options 配置选项
     */
    constructor(url: string, options: SSEOptions<T> = {}) {
        this.url = this.handerUrl(url, options.params);
        this.options = {
            autoReconnect: true,
            reconnectInterval: 3000,
            heartbeatTimeout: 30000,
            ...options,
        };
        this.connect();
    }

    /**
     * 处理 URL
     * @param url
     * @returns
     */
    private handerUrl(url: string, params?: Record<string, any>): string {
        const query = params ? `?${new URLSearchParams(params).toString()}` : '';
        const URLPattern = new URL(url, baseURL);
        return URLPattern.href + query;
    }

    /**
     * 获取请求配置
     * @private
     */
    private getEventSourceConfig(): EventSourcePolyfillInit {
        const store = authStore();

        // 请求头
        const headers: Record<string, string> = {
            'Accept': 'text/event-stream',
            'Cache-Control': 'no-cache',
        };

        // 添加 token
        if (store.accessToken) {
            headers['Authorization'] = store.accessToken;
        }

        // 合并自定义头部
        if (this.options.headers) {
            Object.assign(headers, this.options.headers);
        }

        // 返回配置
        return {
            headers,
            withCredentials: true,
            heartbeatTimeout: this.options.heartbeatTimeout,
        };
    }

    /**
     * 刷新 accessToken
     * @private
     */
    private async refreshAccessToken(): Promise<boolean> {
        // 防止重复刷新
        if (this.isRefreshingToken) {
            return false;
        }

        const store = authStore();
        const refreshToken = store.refreshToken;

        if (!refreshToken) {
            return false;
        }

        try {
            this.isRefreshingToken = true;
            const response = await axios.post(`${baseURL}/refresh`, {}, { withCredentials: true, headers: { "X-Refresh-Token": refreshToken } });
            const accessToken = response?.headers["authorization"];
            if (accessToken) {
                // 保存token到状态库
                store.setAccessToken(accessToken)
                return true;
            } else {
                throw new Error('刷新 token 响应格式错误');
            }
        } catch (error: any | null) {
            this.isRefreshingToken = false;
            // 触发错误回调
            this.options.onError?.(new Error(error?.message));
            return false;
        } finally {
            this.isRefreshingToken = false;
        }
    }

    /**
     * 处理 token 过期
     * @private
     */
    private async handleTokenExpired(): Promise<void> {
        // 先断开当前连接
        this.disconnect();

        // 刷新 token
        const refreshSuccess = await this.refreshAccessToken();

        if (refreshSuccess) {
            console.log('Token 刷新成功，准备重新连接');
            // 延迟一下再重连
            setTimeout(() => {
                this.isConnected = false;
                this.cleanup();
                if (this.options.autoReconnect && !this.isDisconnecting) {
                    this.scheduleReconnect();
                }
            }, 1000);
        } else {
            console.error('Token 刷新失败，停止自动重连');
            // 停止自动重连，避免无限循环
            this.options.autoReconnect = false;
        }
    }

    /**
     * 建立 SSE 连接
     * @private
     */
    private connect(): void {
        // 清理之前的连接
        this.disconnect();

        try {
            this.eventSource = new EventSourcePolyfill(this.url, this.getEventSourceConfig());

            // 设置事件监听器
            this.setupEventListeners();

            this.isConnected = true;
            this.lastMessageTime = Date.now();

            // 触发连接打开回调
            this.options.onOpen?.();

            // 设置心跳检测
            this.setupHeartbeatCheck();

        } catch (error) {
            this.handleError(error as Error);
        }
    }

    /**
     * 设置事件监听器
     * @private
     */
    private setupEventListeners(): void {
        if (!this.eventSource) return;

        // 连接打开事件
        this.eventSource.onopen = () => {
            console.log('SSE连接已建立');
            this.isConnected = true;
            this.lastMessageTime = Date.now();
        };

        // 消息接收事件
        this.eventSource.onmessage = (event) => {
            this.lastMessageTime = Date.now();
            this.handleMessage(event);
        };

        // 错误事件
        this.eventSource.onerror = (event) => {
            console.error('SSE连接错误:', event);
            this.handleError(new Error(event.target));
        };
    }

    /**
     * 处理消息
     * @private
     */
    private handleMessage(event: any): void {
        try {
            const data = event.data;
            if (!data) return;

            let parsedData: any;
            try {
                parsedData = JSON.parse(data);
            } catch {
                parsedData = data;
            }

            // 检查是否是 4001 错误（token 需要刷新）
            if (parsedData?.code === 4001 && parsedData.success === false) {
                this.handleTokenExpired();
                return;
            }

            // 正常消息传递给回调
            this.options.onMessage?.(parsedData as T);
            this.reconnectAttempts = 0;

        } catch (error) {
            console.error('处理SSE消息错误:', error);
        }
    }

    /**
     * 设置心跳检测
     * @private
     */
    private setupHeartbeatCheck(): void {
        if (this.heartbeatTimer) {
            clearInterval(this.heartbeatTimer);
        }

        this.heartbeatTimer = window.setInterval(() => {
            const timeSinceLastMessage = Date.now() - this.lastMessageTime;
            if (timeSinceLastMessage > (this.options.heartbeatTimeout || 30000)) {
                this.handleError(new Error("SSE心跳超时"));
            }
        }, 15000); // 每15秒检查一次
    }

    /**
     * 处理错误
     * @private
     */
    private handleError(error: Error): void {
        this.isConnected = false;
        this.cleanup();
        this.options.onError?.(error);
        if (this.options.autoReconnect && !this.isDisconnecting) {
            // 触发重连
            this.scheduleReconnect();
        }
    }

    /**
     * 安排重新连接
     * @private
     */
    private scheduleReconnect(): void {
        if (this.reconnectTimer) {
            clearTimeout(this.reconnectTimer);
        }

        // 检查重连次数限制
        if (this.reconnectAttempts >= this.maxReconnectAttempts) {
            console.warn("SSE重连次数已达上限，停止重连");
            this.options.onError?.(new Error('SSE重连次数已达上限'));
            return;
        }

        // 重连次数加一
        this.reconnectAttempts++;

        // 指数退避策略
        const delay = Math.min((this.options.reconnectInterval || 3000) * Math.pow(1.5, this.reconnectAttempts - 1), 30000);

        this.reconnectTimer = window.setTimeout(() => {
            console.log(`第${this.reconnectAttempts}次尝试重连， 延迟${delay}毫秒...`);
            this.connect();
        }, delay);
    }

    /**
     * 清理资源
     * @private
     */
    private cleanup(): void {
        if (this.eventSource) {
            this.eventSource.close();
            this.eventSource = null;
        }

        if (this.heartbeatTimer) {
            clearInterval(this.heartbeatTimer);
            this.heartbeatTimer = null;
        }
    }

    /**
     * 主动断开连接
     */
    public disconnect(): void {
        if (this.isDisconnecting) return;
        this.isDisconnecting = true;

        console.log("断开SSE连接");
        this.cleanup();

        if (this.reconnectTimer) {
            clearTimeout(this.reconnectTimer);
            this.reconnectTimer = null;
        }

        this.isConnected = false;
        this.isDisconnecting = false;
    }

    /**
     * 获取当前连接状态
     */
    public getConnectionStatus(): boolean {
        return this.isConnected;
    }

    /**
     * 获取重连次数
     */
    public getReconnectAttempts(): number {
        return this.reconnectAttempts;
    }
}


/**
 * 通用SSE请求
 * @param url 请求路径
 * @param onMessage 接收到消息时的回调
 * @returns 
 */
const request = <T = any>(url: string, onMessage: SSEMessageCallback<T>): SSE<T> => {
    return new SSE<T>(url, { onMessage });
}

/**
 * 暴露
 */
export {
    request,
    SSE,
};